home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 1999 November / SOTMC_Nov1999-Ultimate.iso / mac / REALbasic ƒ / Examples / Techniques / Examples by Thomas Tempelmann / TT's HideMenubar-Plugin / Source Code (CW Pro 3) / Plugin Source.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-03  |  8.2 KB  |  315 lines  |  [TEXT/CWIE]

  1. /*
  2.  * REALbasic-Plugin for hiding the Menu Bar (including the rounded corners
  3.  * as well as other floating objects, like the Control Strip and
  4.  * the detachable Application Floater from OS 8.5 and beyond).
  5.  *
  6.  * Note that it is OS 8.5-savvy, and also automatically takes care
  7.  * of restoring the MenuBar when the app quits unexpectedly (due to
  8.  * a crash) or when the app is suspended (brought to the background).
  9.  * Other similar plugins may not have these important features!
  10.  * (I'm not trying to sell you something here, I just want to help
  11.  * you make your software a bit safer :-)
  12.  *
  13.  * This code is freeware, you may use and extend it as you like.
  14.  *
  15.  * The enclosed project file was created using CodeWarrior Pro 3.
  16.  * To compile it, you also need the "HideMenubarEtc" sample code
  17.  * from Apple. It can be downloaded by logging onto
  18.  *   http://www.apple.com/developer
  19.  * and searching for "HideMenubarEtc". You should find a file
  20.  * with exactly that name available for downloading (it's part
  21.  * of the Toolbox Sample Code).
  22.  * To create the plugin, you need to make the target "Create Fat Plugin".
  23.  *
  24.  * It was written on March 8, 99 by Thomas Tempelmann.
  25.  * More RB-related stuff can be found here: <http://www.tempel.org/rb>
  26.  *
  27.  * Updated May 3, 99 for v1.1:
  28.  *  - added the ability to set a background window (using SetBackgroundWindow)
  29.  *    that then will not brought to the front when the user clicks on it.
  30.  *  - fixed a bug that caused PPC plugins to crash under OS 8.5 and beyond
  31.  *
  32.  * Enjoy and contribute!
  33.  */
  34.  
  35. #include <stdlib.h>
  36. #include <MixedMode.h>
  37. #include <SetupA4.h>
  38. #include <ControlStrip.h>
  39.  
  40. #ifdef powerc
  41.     #include "68K Interface.h"
  42. #endif
  43.  
  44. #include "MenusLib Interface.h"
  45. #include "ShowHideMenubar.h"
  46. #include "ShowHideCorners.h"
  47. #include "rb_plugin.h"
  48.  
  49.  
  50. const ProcInfoType wneProcInfo =
  51.     kPascalStackBased |
  52.     RESULT_SIZE(SIZE_CODE(sizeof(Boolean))) |
  53.     STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short))) |
  54.     STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(EventRecord*))) |
  55.     STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(UInt32))) |
  56.     STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(RgnHandle)));
  57.     
  58. #ifdef powerc
  59. typedef UniversalProcPtr wneProc;
  60. #else
  61. typedef pascal Boolean (*wneProc) (short eventMask, EventRecord* theEvent, UInt32 sleep, RgnHandle mouseRgn);
  62. #endif
  63.  
  64. far static    Boolean ControlStripExists, HasOS85MenuMgr, qdSet, gCSIsHidden, gMBIsHidden;
  65. far static    UniversalProcPtr gOldExitToShell, gNewExitToShell, gNewWNE;
  66. far static    wneProc gOldWNE;
  67. far static    WindowPtr gBackgroundWindow;
  68. far            QDGlobals qd;
  69.  
  70.  
  71. static void initQD ();
  72. static void deInstall ();
  73.  
  74.  
  75. //
  76. // taken from Universal Headers 3.2:
  77. //
  78.     // Routines available in Mac OS 8.5 and later
  79.     EXTERN_API(Boolean) IsMenuBarVisible (void);
  80.     EXTERN_API(void) ShowMenuBar (void);
  81.     EXTERN_API(void) HideMenuBar (void);
  82.  
  83.  
  84. static long isMenuBarVisible ()
  85. {
  86.     if (HasOS85MenuMgr) {
  87.         return MenusLibIsMenuBarVisible ();
  88.     } else {
  89.         return GetMBarHeight () > 1;    // due to a Technote from Apple, a menu bar hight of 1 is to be considered a hidden menu
  90.     }
  91. }
  92.  
  93. static void hideMenuBar ()
  94. {
  95.     gMBIsHidden = true;
  96.     if (!qdSet) initQD();
  97.     if (HasOS85MenuMgr) {
  98.         MenusLibHideMenuBar ();
  99.     } else {
  100.         SetMBarState (HIDE);
  101.     }
  102.     SetCornersState (HIDE);
  103. }
  104.  
  105. static void showMenuBar (void)
  106. {
  107.     gMBIsHidden = false;
  108.     if (!qdSet) initQD();
  109.     SetCornersState (SHOW);
  110.     if (HasOS85MenuMgr) {
  111.         MenusLibShowMenuBar ();
  112.     } else {
  113.         SetMBarState (SHOW);
  114.     }
  115. }
  116.  
  117.  
  118. static void hideControlStrip ()
  119. {
  120.     if (ControlStripExists) {
  121.         if (!qdSet) initQD();
  122.         gCSIsHidden = true;
  123.         SBShowHideControlStrip (false);
  124.     }
  125. }
  126.  
  127. static void showControlStrip ()
  128. {
  129.     if (ControlStripExists) {
  130.         if (!qdSet) initQD();
  131.         gCSIsHidden = false;
  132.         SBShowHideControlStrip (true);
  133.     }
  134. }
  135.  
  136. static long controlStripExists ()
  137. {
  138.     return ControlStripExists;
  139. }
  140.  
  141. static long isControlStripVisible ()
  142. {
  143.     if (ControlStripExists) {
  144.         return SBIsControlStripVisible ();
  145.     }
  146.     return false;
  147. }
  148.  
  149. static void restoreMenuBarEtc ()
  150. // should be called when app quits
  151. // (at least when the app is run from inside the RB IDE!)
  152. {
  153.     deInstall ();
  154. }
  155.  
  156. static void setBackgroundWindow (REALwindow wdw)
  157. {
  158.     if (wdw == NULL) {
  159.         gBackgroundWindow = nil;
  160.     } else {
  161.         if (!qdSet) initQD();
  162.         gBackgroundWindow = REALGetWindowHandle (wdw);
  163.     }
  164. }
  165.  
  166.  
  167. REALexport pluginExports[] = {
  168.     { nil, isMenuBarVisible },
  169.     { nil, hideMenuBar },
  170.     { nil, showMenuBar },
  171.     { nil, isControlStripVisible },
  172.     { nil, hideControlStrip },
  173.     { nil, showControlStrip },
  174.     { nil, restoreMenuBarEtc },
  175.     { nil, controlStripExists },
  176.     { nil, setBackgroundWindow },
  177. };
  178.  
  179. short pluginExportCode = sizeof(pluginExports) / sizeof(REALexport);
  180.  
  181. REALmethodDefinition methods[] = {
  182.     {0,    "IsMenuBarVisible() as Boolean"},
  183.     {1,    "HideMenuBar()"},
  184.     {2,    "ShowMenuBar()"},
  185.     {3,    "IsControlStripVisible() as Boolean"},
  186.     {4,    "HideControlStrip()"},
  187.     {5,    "ShowControlStrip()"},
  188.     {6,    "RestoreMenuBar()"},
  189.     {7,    "ControlStripExists() as Boolean"},
  190.     {8, "SetBackgroundWindow(w as Window)"},
  191. };
  192.  
  193.  
  194. static void handleOSEvt (EventRecord *theEvent)
  195. {
  196.     Boolean suspend = (theEvent->message & 1) == 0;
  197.     if (suspend) {
  198.         if (gMBIsHidden) {
  199.             showMenuBar ();
  200.             if (ControlStripExists && gCSIsHidden) {
  201.                 SBShowHideControlStrip (true);
  202.             }
  203.             gMBIsHidden = true;
  204.         }
  205.     } else {
  206.         if (gMBIsHidden) {
  207.             if (ControlStripExists && gCSIsHidden) {
  208.                 SBShowHideControlStrip (false);
  209.             }
  210.             hideMenuBar ();
  211.         }
  212.     }
  213. }
  214.  
  215. static pascal Boolean wneHook (EventMask eventMask, EventRecord* theEvent, UInt32 sleep, RgnHandle mouseRgn)
  216. {
  217.     Boolean b = CALL_FOUR_PARAMETER_UPP (gOldWNE, wneProcInfo, eventMask, theEvent, sleep, mouseRgn);
  218.     if (theEvent->what == osEvt && (theEvent->message & 0xFF000000) == 0x01000000) {
  219.         // our RB application is (de)activated -> show/hide the menu bar
  220.         handleOSEvt (theEvent);
  221.     } else if (gBackgroundWindow != nil && theEvent->what == mouseDown) {
  222.         // mouse button was clicked -> check if it is clicked in our background window
  223.         WindowPtr theWin;
  224.         short where = FindWindow (theEvent->where, &theWin);
  225.         if (where == inContent && theWin == gBackgroundWindow) {
  226.             // yes, user clicked into the background window -> disable this event in order to prevent this window to be brought to front
  227.             theEvent->what = nullEvent;
  228.             b = false;
  229.         }
  230.     }
  231.     return b;
  232. }
  233.  
  234. static void deInstall ()
  235. {
  236.     if (gOldExitToShell) SetToolTrapAddress (gOldExitToShell, _ExitToShell);
  237.     gOldExitToShell = nil;
  238.     if (gOldWNE) SetToolTrapAddress ((UniversalProcPtr)gOldWNE, _WaitNextEvent);
  239.     gOldWNE = nil;
  240.     if (gMBIsHidden) {
  241.         showMenuBar ();
  242.         if (gCSIsHidden) showControlStrip ();
  243.     }
  244.     gCSIsHidden = false;
  245.     qdSet = false;
  246. }
  247.  
  248. static pascal void quit (void)
  249. {
  250.     EnterCallback();
  251.     deInstall ();
  252.     ExitCallback();
  253.     ExitToShell ();
  254. }
  255.  
  256.  
  257. static void initQD ()
  258. // called when any of the RB functions here get called the first time
  259. {
  260.     QDGlobals *orig_qd = (QDGlobals*) (*(Ptr*)LMGetCurrentA5() - offsetof(QDGlobals, thePort));
  261.     qd = *orig_qd;
  262.     qdSet = true;
  263.     
  264.     gBackgroundWindow = nil;
  265.  
  266.     // install a WNE hook so that we are notified when our app gets pushed in
  267.     // the background, so that we can restore the MenuBar for so long.
  268.     gOldWNE = (wneProc) NGetTrapAddress (_WaitNextEvent, 1);
  269.     SetToolTrapAddress (gNewWNE, _WaitNextEvent);
  270.     
  271.     // install a hook onto ExitToShell() in order to restore everything in case the app crashes
  272.     gOldExitToShell = NGetTrapAddress (_ExitToShell, 1);
  273.     SetToolTrapAddress (gNewExitToShell, _ExitToShell);
  274. }
  275.  
  276.  
  277. static void init ()
  278. {
  279.     long gestaltAnswer;
  280.  
  281.     // check for Control Strip
  282.     Gestalt (gestaltControlStripAttr, &gestaltAnswer);
  283.     ControlStripExists = (gestaltAnswer & (1 << gestaltControlStripExists)) != 0;
  284.  
  285.     // check for new Menu Mgr (OS 8.5)
  286.     Gestalt ('menu', &gestaltAnswer);
  287.     HasOS85MenuMgr = gestaltAnswer & 1;
  288.     
  289.     if (HasOS85MenuMgr) {
  290.         // load MenusLib stub for access to MenusLib
  291.         if (!InitMenusLibInterface ()) {
  292.             HasOS85MenuMgr = false;    // if loading of stub fails, then use old technique
  293.         }
  294.     }
  295.     
  296.     // Save the global A4 register for the hook/filter functions
  297.     PrepareCallback ();
  298.     
  299.     // allocate the ProcPtrs
  300.     gNewExitToShell = NewRoutineDescriptor ((ProcPtr)quit, kPascalStackBased, GetCurrentISA());
  301.     gNewWNE = NewRoutineDescriptor ((ProcPtr)wneHook, wneProcInfo, GetCurrentISA());
  302.     gOldWNE = (wneProc)nil;
  303.     gOldExitToShell = (UniversalProcPtr)nil;
  304.  
  305.     gCSIsHidden = gMBIsHidden = qdSet = false;
  306. }
  307.  
  308. void PluginEntry (void)
  309. {
  310.     for (int i = 0; i < pluginExportCode; ++i) {
  311.         REALRegisterMethod (&methods[i]);
  312.     }
  313.     init ();
  314. }
  315.